// =============================================================================
//  Spangles Analyzer
//
//  Copyright(c) 2008
//  See LICENSE.txt for licensing information.
// =============================================================================

package com.google.spangles.main;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.google.spangles.domain.Color;
import com.google.spangles.domain.GameState;
import com.google.spangles.domain.GameplayOptions;
import com.google.spangles.view.Renderer;
import com.google.spangles.view.Visualization;
import com.google.spangles.view.renderers.GraphicsOptions;
import com.google.spangles.view.renderers.GraphicsRenderer;
import com.google.spangles.view.renderers.ShellRenderer;
import com.google.spangles.view.service.VisualizationService;
import com.google.spangles.view.service.impl.VisualizationServiceImpl;

/**
 * (Description)
 * (Any invariants [conditions that are always true] )
 * (Usage instructions, and/or examples)
 * (TODOs, ASSUMPTIONs, etc.)
 * (Known Bugs)
 * (Concurrency strategy - not thread safe or how it's thread safe)
 * 
 * @author Chris
 */
public class ReplayGraphics
{
   private static int BUFFER_SIZE = 4096;
   
   InputStream is;
   
   /**
    * @param is
    */
   public ReplayGraphics(InputStream is)
   {
      this.is = is;
   }

   /**
    * (Description - what the method does and why)
    * (Visibility decision, if not obvious)
    * (Pre/Post Conditions)
    * (Usage examples)
    * (Algorithmic notes)
    * (Concurrency issues)
    * @param args
    * @throws IOException 
    */
   public static void main(String[] args) throws IOException
   {
      ReplayGraphics r = new ReplayGraphics(System.in);
      r.run();
   }
      
   public void run() throws IOException
   {
      // Load the properties file
      Properties props = new Properties();
      InputStream pis = getClass().getClassLoader().getResourceAsStream("spangles.properties");
      props.load(pis);
      pis.close();
      
      GraphicsOptions go = new GraphicsOptions(props);
      GameplayOptions gpo = new GameplayOptions(props);
      
      // Read the entire of system.in as a byte array.
      String buffer = readInput(is);
      
      Pattern p = Pattern.compile("(?s)(\\d+)\\s+([A-Z])(\\d+)\\s");
      Matcher m = p.matcher(buffer);
      
      GameState gs = GameState.createEmpty();
      
      while(m.find())
      {
         String move = m.group(1);
         String column = m.group(2);
         String row = m.group(3);
         
         System.out.println(move + " " + column + row);
         
         Color winner = gs.playRelative( column.codePointAt(0) - "A".codePointAt(0), Integer.valueOf(row)-1);
         if (winner != null)
         {
            System.out.println("Game won by " + winner);
            break;
         }
      }
      
      GameState toVisualize = gs;
      
      if(gpo.isDeadTiles())
      {
         toVisualize = gs.deadTileElimination();
      }
      
      VisualizationService vs = new VisualizationServiceImpl();
      Visualization v = vs.visualize(toVisualize);
      
      Renderer r = new GraphicsRenderer(go);
      r.render(v);
   }

   /**
    * (Description - what the method does and why)
    * (Visibility decision, if not obvious)
    * (Pre/Post Conditions)
    * (Usage examples)
    * (Algorithmic notes)
    * (Concurrency issues)
    * @param in
    * @return
    * @throws IOException 
    */
   private static String readInput(InputStream in) throws IOException
   {
      StringBuilder sb = new StringBuilder();
      
      byte[] b = new byte[BUFFER_SIZE];
      
      boolean reading = true;
      
      while (reading)
      {
         int bytesRead = in.read(b);
         if (bytesRead == -1)
         {
            reading = false;
         }
         else
         {
            String chunk = new String(b, 0, bytesRead, "ISO-8859-1");
            sb.append(chunk);
         }
      }
      return sb.toString();
   }

}
